In [1]:
%matplotlib inline

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

import matplotlib.pyplot as plt

pd.options.display.float_format = '{:.4g}'.format

import enlopy as el

Generate energy loads using monthly and daily profiles for a working and a non-working day

Create random monthly and daily loads


In [2]:
ML  = (np.cos(2 * np.pi/12 * np.linspace(0,11,12)) * 50 + 100 ) * 1000  # monthly load
ML = el.make_timeseries(ML) #convenience wrapper around pd.DataFrame with pd.DateTimeindex
ML.plot()


Out[2]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f47bc83e668>

Create normalized random daily load for a working and non-working day


In [3]:
DWL =  el.gen_daily_stoch_el() #daily load working

DNWL = el.gen_daily_stoch_el() #daily load non working

plt.plot(DNWL)
plt.plot(DWL)


Out[3]:
[<matplotlib.lines.Line2D at 0x7f47bc4aea58>]

In [4]:
#Define the weighting factor of energy during working and non-working days.
Weight = .55 # i.e energy will be split 55% in working day 45% non working day

Load1 =  el.gen_load_from_daily_monthly(ML, DWL, DNWL, Weight)
Load1.name = 'House1'
Load1.plot(figsize=(17,3), linewidth =.2, grid = False);


Check if the total sum of energy is the same


In [5]:
print ('error = {:.2f}'.format(Load1.sum() - ML.sum()))


error = 0.00

Reshape (days - hours) and plot heatmap


In [6]:
el.reshape_timeseries(Load1, x='month', y='hour')


Out[6]:
month 1 2 3 4 5 6 7 8 9 10 11 12
hour
0 971.8 929.4 809.8 651.4 482.2 369.3 326.4 364.5 488.6 647.8 808 935.3
1 1254 1200 1045 844.5 617.6 478.8 423.9 466.9 633.4 835.7 1040 1215
2 1448 1387 1207 977.7 711.3 554.3 491.1 537.8 733.3 965.4 1200 1407
3 2005 1918 1671 1346 992.1 763.4 675 750 1010 1336 1665 1935
4 2346 2245 1955 1575 1162 892.9 789.3 878.7 1181 1564 1950 2262
5 3380 3232 2816 2264 1678 1284 1134 1269 1698 2253 2811 3250
6 5136 4911 4280 3437 2554 1949 1721 1931 2578 3424 4273 4933
7 5267 5033 4389 3515 2630 1993 1758 1988 2636 3511 4387 5039
8 5183 4952 4319 3457 2590 1960 1729 1958 2593 3455 4319 4954
9 5521 5275 4601 3682 2759 2088 1841 2086 2762 3681 4600 5277
10 5782 5523 4819 3851 2895 2184 1925 2189 2888 3855 4821 5517
11 6126 5853 5105 4086 3062 2316 2043 2315 3064 4084 5105 5855
12 6340 6055 5283 4219 3178 2392 2108 2403 3164 4227 5287 6042
13 6937 6629 5781 4631 3462 2626 2316 2617 3473 4625 5778 6639
14 7671 7325 6393 5099 3851 2891 2547 2912 3824 5114 6401 7299
15 9060 8648 7550 6012 4559 3409 3001 3446 4509 6040 7565 8601
16 9768 9323 8140 6479 4919 3673 3233 3718 4859 6512 8157 9267
17 1.05e+04 1.003e+04 8751 6999 5253 3968 3499 3971 5249 7001 8752 1.003e+04
18 1.094e+04 1.045e+04 9114 7290 5469 4133 3645 4135 5468 7291 9114 1.045e+04
19 1.081e+04 1.033e+04 9008 7202 5408 4084 3601 4089 5402 7206 9010 1.032e+04
20 1.02e+04 9745 8504 6792 5114 3851 3394 3866 5094 6803 8509 9726
21 9450 9029 7875 6303 4722 3574 3152 3570 4727 6300 7874 9033
22 7851 7503 6543 5242 3918 2972 2622 2962 3931 5234 6539 7515
23 6051 5784 5043 4046 3013 2294 2025 2278 3035 4034 5036 5805

In [7]:
el.plot_heatmap(Load1, edgecolors='none')



In [8]:
el.plot_heatmap(Load1, x='hour', y='week',bins=10, aggfunc='mean', cmap='Blues' ,edgecolors='w')


Plots

Plot percentiles


In [9]:
el.plot_percentiles(Load1, x='week', zz='hour')



In [10]:
el.plot_percentiles(Load1, x='hour', zz='dayofyear', perc_list=[[1,99], [25,75], 50],color='green')


3d plots


In [11]:
el.plot_3d(Load1, bins=50, cmap='inferno')



In [12]:
el.plot_3d(Load1, x='hour', y='month', aggfunc='mean', cmap='Blues')


Boxplot


In [13]:
el.plot_boxplot(Load1, by='day')


Rugplot


In [14]:
el.plot_rug(Load1, on_off=False, cmap='Greys')


It can accept a dataframe of timeseries and optionally normalize by the maximum value of the whole DataFrame


In [15]:
# Generate dummy dataframe of load profiles
df_many = pd.concat([Load1, 3 * Load1, Load1['Jun 2015':'Nov 2015']], axis=1)
df_many.columns = ['House1', 'House2', 'House3']

In [16]:
el.plot_rug(df_many, cmap='Greens', fig_title='Many houses', normalized=True)


Get and plot Load Duration Curve of load


In [17]:
el.get_LDC(Load1)


Out[17]:
(array([1.14155251e-04, 2.28310502e-04, 3.42465753e-04, ...,
        9.99771689e-01, 9.99885845e-01, 1.00000000e+00]),
 array([393.06740417, 393.06740417, 393.06740417, ...,   7.24227434,
          7.24227434,   7.24227434]))

In [18]:
el.plot_LDC(Load1, x_norm=False)



In [19]:
el.plot_LDC(Load1, y_norm=True, color='Orange')



In [20]:
el.plot_LDC(Load1, zoom_peak=True)



In [21]:
#Works also for 2-D
el.plot_LDC(df_many[['House1', 'House2']])



In [22]:
el.plot_LDC(df_many[['House1', 'House2']],zoom_peak=True)



In [23]:
el.plot_LDC(df_many[['House1', 'House2']],stacked=False)


Archetypes


In [24]:
plt.plot(el.get_load_archetypes(Load1,2));



In [25]:
el.get_load_archetypes(Load1, 5, plot_diagnostics=True);


<Figure size 432x288 with 0 Axes>

Add noise to a load


In [26]:
Load1_noise = el.add_noise(Load1, 3, 100) # Gauss Markov noise

fig = plt.figure(figsize=(14,3))

#plt.plot(Load1_noise,linewidth =.3)
Load1_noise.plot(figsize=(17,3), linewidth =.2, grid = False)
Load1_noise.name='Noisy'


Forcing Datetimeindex into passed timeseries.For more accurate results please pass a pandas time-indexed timeseries.

In [27]:
Load1_noise.iloc[0:100].plot()
Load1.iloc[0:100].plot()


Out[27]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f47bc2b4320>

In [28]:
el.plot_LDC(Load1_noise)
el.plot_LDC(Load1, color='g')


/home/kotzer/anaconda3/envs/enlopy/lib/python3.7/site-packages/matplotlib/figure.py:98: MatplotlibDeprecationWarning: 
Adding an axes using the same arguments as a previous axes currently reuses the earlier instance.  In a future version, a new instance will always be created and returned.  Meanwhile, this warning can be suppressed, and the future behavior ensured, by passing a unique label to each axes instance.
  "Adding an axes using the same arguments as a previous axes "

Gather statistics


In [29]:
el.get_load_stats(Load1)


Out[29]:
2015
Autocorrelation(1) 0.9369
Average 137
Biggest duration of consecutive zero load 0
Load Factor (peakiness) 0.3485
Load ratio (max/min) 54.27
Max 393.1
Min (2%) 7.242
Periodicity (2190.0, 162.0)
Ramps (98%) (-111.031, 47.785)
Sum 1.2e+06
Total Zero load duration 0
Trend -0.004203

We can also check the statistics per defined time period. Example for month ('m'):


In [30]:
el.get_load_stats(Load1, per='m')


Out[30]:
2015-01 2015-02 2015-03 2015-04 2015-05 2015-06 2015-07 2015-08 2015-09 2015-10 2015-11 2015-12
Autocorrelation(1) 0.9091 0.9093 0.9106 0.9099 0.91 0.9099 0.9096 0.9114 0.9099 0.9091 0.9109 0.9096
Average 201.6 213.2 168 138.9 100.8 78.75 67.2 76.21 104.2 134.4 173.6 192.6
Biggest duration of consecutive zero load 0 0 0 0 0 0 0 0 0 0 0 0
Load Factor (peakiness) 0.542 0.5425 0.542 0.5445 0.5387 0.5445 0.5454 0.5387 0.5445 0.542 0.541 0.5454
Load ratio (max/min) 17.01 17.01 17.01 17.01 17.01 17.01 17.01 17.01 17.01 17.01 17.01 17.01
Max 372 393.1 310 255.1 187.1 144.6 123.2 141.5 191.3 248 320.9 353.2
Min (2%) 21.86 23.1 18.22 14.99 11 8.5 7.242 8.315 11.24 14.57 18.86 20.76
Periodicity (124.0, 23.0) (112.0, 24.0) (124.0, 23.0) (120.0, 24.0) (124.0, 23.0) (120.0, 24.0) (124.0, 23.0) (124.0, 23.0) (120.0, 24.0) (124.0, 23.0) (120.0, 24.0) (124.0, 23.0)
Ramps (98%) (-178.112, 61.215) (-188.222, 64.689) (-148.426, 51.012) (-122.145, 41.979) (-89.611, 30.798) (-69.254, 23.802) (-59.005, 20.279) (-67.744, 23.283) (-91.608, 31.485) (-118.741, 40.81) (-153.659, 52.811) (-169.11, 58.121)
Sum 1.5e+05 1.433e+05 1.25e+05 1e+05 7.5e+04 5.67e+04 5e+04 5.67e+04 7.5e+04 1e+05 1.25e+05 1.433e+05
Total Zero load duration 0 0 0 0 0 0 0 0 0 0 0 0
Trend 0.01395 0.01724 0.01054 0.01173 0.00504 0.00219 0.006141 0.006281 0.005846 0.009302 0.008844 0.01267

Load Shifting

The following function performs load shifting (or peak shaving) from peak to off-peak timesteps based on given specifications, percentage of peak reduction and percentage of hours per month to peak.


In [31]:
Load1_DR = el.gen_demand_response(Load1, 0.15, 0.30)

In [32]:
Load1[0:100].plot()
Load1_DR[0:100].plot()


Out[32]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f47ba39c400>

In [33]:
el.get_load_stats(Load1)


Out[33]:
2015
Autocorrelation(1) 0.9369
Average 137
Biggest duration of consecutive zero load 0
Load Factor (peakiness) 0.3485
Load ratio (max/min) 54.27
Max 393.1
Min (2%) 7.242
Periodicity (2190.0, 162.0)
Ramps (98%) (-111.031, 47.785)
Sum 1.2e+06
Total Zero load duration 0
Trend -0.004203

As shown below it is less peaky as expected


In [34]:
el.get_load_stats(Load1_DR)


Out[34]:
2015
Autocorrelation(1) 0.9231
Average 136.2
Biggest duration of consecutive zero load 0
Load Factor (peakiness) 0.412
Load ratio (max/min) 15.34
Max 330.5
Min (2%) 21.55
Periodicity (2190.0, 162.0)
Ramps (98%) (-72.709, 51.012)
Sum 1.193e+06
Total Zero load duration 0
Trend -0.004177

In [35]:
el.plot_LDC(Load1_DR, color='g')
el.plot_LDC(Load1, ax=plt.gca())


Sample new loads from load duration curve


In [36]:
Load1a = el.gen_load_from_LDC(el.get_LDC(Load1))
fig = plt.figure(figsize=(14,3))
plt.plot(Load1a, linewidth =.3)


Out[36]:
[<matplotlib.lines.Line2D at 0x7f47b98d5400>]

Check whether they have the same distribution


In [37]:
el.plot_LDC(Load1a)
el.plot_LDC(Load1, color='red', ax=plt.gca())


Forcing Datetimeindex into passed timeseries.For more accurate results please pass a pandas time-indexed timeseries.

In [ ]: